#pragma once
#include<brpc/channel.h>
#include<string>
#include<vector>
#include<memory>
#include<unordered_map>
#include<mutex>

namespace ns_server_manager
{
    // 类1：每个服务可由多个节点提供 ——> 1 VS n 个通信信道
    class ServerChannels
    {
        using ChannelPtr=std::shared_ptr<brpc::Channel>; 

    public:
        ServerChannels(const std::string& ServerName)
            :_server_name(ServerName)
            ,_cur_index(0)
        {}

        // 选择一个服务信道
        ChannelPtr ChooseOne()
        {
            if (!_channels.empty())
            {
                ChannelPtr one =_channels[_cur_index];
                _cur_index = ++_cur_index % _channels.size();
                return one;
            }

            // 没有可服务节点
            return nullptr;
        }

        // 添加一个信道
        void Add(const std::string& ip_port)
        {
            ChannelPtr channel(new brpc::Channel);
            brpc::ChannelOptions cops;

            channel->Init(ip_port.c_str(), &cops);
            _channels.push_back(channel);

            _manager.insert({ip_port, _channels.size() - 1});
        }

        // 节点服务下线，进行删除
        void Del(const std::string& ip_port)
        {
            std::cout << "test" << std::endl;
            if (!_channels.empty())
            {
                std::cout << "test1" << std::endl;
                uint8_t index = _manager[ip_port];
                std::cout << "test2" << std::endl;
                auto it = _channels.begin();
                std::cout << "test3" << std::endl;
                for (int i = 0; i < index; ++i)
                {
                    ++it;
                }

                std::cout << "test4" << std::endl;
                _channels.erase(it);
                std::cout << "test5" << std::endl;
                _manager.erase(ip_port);
                std::cout << "test6" << std::endl;
                // 对 _cur_index 检查修正
                _cur_index = _cur_index % _channels.size();
                std::cout << "test6" << std::endl;
            } 
        }

    private:
        std::string _server_name; //服务名称

        // 信道选择的负载策略：RR
        uint8_t _cur_index;
        std::vector<ChannelPtr> _channels;

        std::unordered_map<std::string, uint8_t> _manager; // 下线管理：ip_port映射channel 
    };

    // 类2：管理所有 "关注"的 服务
    class ServersManager
    {
        using ChannelPtr=std::shared_ptr<brpc::Channel>; 

    public:
        ServersManager(const std::vector<std::string>& servers)
        {
            for (auto& e : servers)
            {
                _servcers.insert({e, ServerChannels(e)});
            }
        }

        // 选择一个可用节点信道
        ChannelPtr ChooseOneChannel(const std::string& server_name)
        {
            std::lock_guard<std::mutex> lock(_mx);
            auto it = _servcers.find(server_name);
            if (it == _servcers.end())
            {
                return nullptr;
            }

            return it->second.ChooseOne();
        }

        // 设置上/下线的回调函数(结合etcd, 异步)
        void Online(const std::string& server_instance, const std::string& ip_port)
        {
            std::lock_guard<std::mutex> lock(_mx);
            std::string server_name = StrHelp(server_instance);
            auto it = _servcers.find(server_name);
            if (it == _servcers.end()) {return;}

            it->second.Add(ip_port);
        }

        void Offline(const std::string& server_instance, const std::string& ip_port)
        {
            std::lock_guard<std::mutex> lock(_mx);
            std::string server_name = StrHelp(server_instance);
            auto it = _servcers.find(server_name);
            if (it == _servcers.end()) {return;}
            it->second.Del(ip_port);
        }
    private:
    // 字符串处理
    std::string StrHelp(const std::string str)
    {
        auto pos = str.find_last_of('/');
        if (pos == std::string::npos)
        {
            return string();
        }

        return str.substr(0, pos);
    }

    private:
        std::mutex _mx;
        std::unordered_map<std::string, ServerChannels> _servcers;
    };
}